from OpenGL import GL, constant
import OpenGL.GL.ARB.gpu_shader_int64 as gsi64
import numpy as np
import glm
import ctypes

dtype_uint8 = np.array([], dtype=np.uint8).dtype
dtype_int8 = np.array([], dtype=np.int8).dtype
dtype_uint16 = np.array([], dtype=np.uint16).dtype
dtype_int16 = np.array([], dtype=np.int16).dtype
dtype_uint32 = np.array([], dtype=np.uint32).dtype
dtype_uint64 = np.array([], dtype=np.uint64).dtype
dtype_int32 = np.array([], dtype=np.int32).dtype
dtype_int64 = np.array([], dtype=np.int64).dtype
dtype_float16 = np.array([], dtype=np.float16).dtype
dtype_float32 = np.array([], dtype=np.float32).dtype
dtype_float64 = np.array([], dtype=np.float64).dtype


class GLInfo:
    primary_types = [
        int,
        float,
        bool,
        np.int8,
        np.uint8,
        np.int16,
        np.uint16,
        np.int32,
        np.uint32,
        np.int64,
        np.uint64,
        np.float16,
        np.float32,
        np.float64,
        dtype_int8,
        dtype_uint8,
        dtype_int16,
        dtype_uint16,
        dtype_int32,
        dtype_uint32,
        dtype_int64,
        dtype_uint64,
        dtype_float16,
        dtype_float32,
        dtype_float64,
        ctypes.c_int8,
        ctypes.c_uint8,
        ctypes.c_int16,
        ctypes.c_uint16,
        ctypes.c_int32,
        ctypes.c_uint32,
        ctypes.c_int64,
        ctypes.c_uint64,
        ctypes.c_float,
        ctypes.c_double,
    ]

    dtype_map = {
        GL.GL_BYTE: np.int8,
        GL.GL_UNSIGNED_BYTE: np.uint8,
        GL.GL_SHORT: np.int16,
        GL.GL_UNSIGNED_SHORT: np.uint16,
        GL.GL_INT: np.int32,
        GL.GL_UNSIGNED_INT: np.uint32,
        gsi64.GL_UNSIGNED_INT64_ARB: np.uint64,
        GL.GL_HALF_FLOAT: np.float16,
        GL.GL_FLOAT: np.float32,
        GL.GL_DOUBLE: np.float64,
    }

    dtype_inverse_map = {
        dtype_int8: GL.GL_BYTE,
        np.int8: GL.GL_BYTE,
        ctypes.c_int8: GL.GL_BYTE,
        bool: GL.GL_BYTE,
        dtype_uint8: GL.GL_UNSIGNED_BYTE,
        np.uint8: GL.GL_UNSIGNED_BYTE,
        ctypes.c_uint8: GL.GL_UNSIGNED_BYTE,
        dtype_int16: GL.GL_SHORT,
        np.int16: GL.GL_SHORT,
        ctypes.c_int16: GL.GL_SHORT,
        dtype_uint16: GL.GL_UNSIGNED_SHORT,
        np.uint16: GL.GL_UNSIGNED_SHORT,
        ctypes.c_uint16: GL.GL_UNSIGNED_SHORT,
        dtype_int32: GL.GL_INT,
        np.int32: GL.GL_INT,
        ctypes.c_int32: GL.GL_INT,
        int: GL.GL_INT,
        dtype_uint32: GL.GL_UNSIGNED_INT,
        np.uint32: GL.GL_UNSIGNED_INT,
        ctypes.c_uint32: GL.GL_UNSIGNED_INT,
        dtype_uint64: gsi64.GL_UNSIGNED_INT64_ARB,
        np.uint64: gsi64.GL_UNSIGNED_INT64_ARB,
        ctypes.c_uint64: gsi64.GL_UNSIGNED_INT64_ARB,
        dtype_float16: GL.GL_HALF_FLOAT,
        np.float16: GL.GL_HALF_FLOAT,
        dtype_float32: GL.GL_FLOAT,
        np.float32: GL.GL_FLOAT,
        ctypes.c_float: GL.GL_FLOAT,
        float: GL.GL_FLOAT,
        dtype_float64: GL.GL_DOUBLE,
        np.float64: GL.GL_DOUBLE,
        ctypes.c_double: GL.GL_DOUBLE,
        glm.vec2: GL.GL_FLOAT,
        glm.vec3: GL.GL_FLOAT,
        glm.vec4: GL.GL_FLOAT,
        glm.bvec2: GL.GL_BYTE,
        glm.bvec3: GL.GL_BYTE,
        glm.bvec4: GL.GL_BYTE,
        glm.ivec2: GL.GL_INT,
        glm.ivec3: GL.GL_INT,
        glm.ivec4: GL.GL_INT,
        glm.uvec2: GL.GL_UNSIGNED_INT,
        glm.uvec3: GL.GL_UNSIGNED_INT,
        glm.uvec4: GL.GL_UNSIGNED_INT,
        glm.dvec2: GL.GL_DOUBLE,
        glm.dvec3: GL.GL_DOUBLE,
        glm.dvec4: GL.GL_DOUBLE,
        glm.mat2x2: GL.GL_FLOAT,
        glm.mat2x3: GL.GL_FLOAT,
        glm.mat2x4: GL.GL_FLOAT,
        glm.mat3x2: GL.GL_FLOAT,
        glm.mat3x3: GL.GL_FLOAT,
        glm.mat3x4: GL.GL_FLOAT,
        glm.mat4x2: GL.GL_FLOAT,
        glm.mat4x3: GL.GL_FLOAT,
        glm.mat4x4: GL.GL_FLOAT,
        glm.dmat2x2: GL.GL_DOUBLE,
        glm.dmat2x3: GL.GL_DOUBLE,
        glm.dmat2x4: GL.GL_DOUBLE,
        glm.dmat3x2: GL.GL_DOUBLE,
        glm.dmat3x3: GL.GL_DOUBLE,
        glm.dmat3x4: GL.GL_DOUBLE,
        glm.dmat4x2: GL.GL_DOUBLE,
        glm.dmat4x3: GL.GL_DOUBLE,
        glm.dmat4x4: GL.GL_DOUBLE,
    }

    np_dtype_map = {
        int: np.int32,
        float: np.float32,
        glm.vec2: np.float32,
        glm.vec3: np.float32,
        glm.vec4: np.float32,
        glm.bvec2: np.int8,
        glm.bvec3: np.int8,
        glm.bvec4: np.int8,
        glm.ivec2: np.int32,
        glm.ivec3: np.int32,
        glm.ivec4: np.int32,
        glm.uvec2: np.uint32,
        glm.uvec3: np.uint32,
        glm.uvec4: np.uint32,
        glm.dvec2: np.float64,
        glm.dvec3: np.float64,
        glm.dvec4: np.float64,
        glm.mat2x2: np.float32,
        glm.mat2x3: np.float32,
        glm.mat2x4: np.float32,
        glm.mat3x2: np.float32,
        glm.mat3x3: np.float32,
        glm.mat3x4: np.float32,
        glm.mat4x2: np.float32,
        glm.mat4x3: np.float32,
        glm.mat4x4: np.float32,
        glm.dmat2x2: np.float64,
        glm.dmat2x3: np.float64,
        glm.dmat2x4: np.float64,
        glm.dmat3x2: np.float64,
        glm.dmat3x3: np.float64,
        glm.dmat3x4: np.float64,
        glm.dmat4x2: np.float64,
        glm.dmat4x3: np.float64,
        glm.dmat4x4: np.float64,
    }

    geometry_ins = [
        "points",
        "lines",
        "lines_adjacency",
        "triangles",
        "triangles_adjacency",
    ]

    blend_equation_map = {
        GL.GL_FUNC_ADD: "+",
        GL.GL_FUNC_SUBTRACT: "-",
        GL.GL_FUNC_REVERSE_SUBTRACT: GL.GL_FUNC_REVERSE_SUBTRACT,
        "+": GL.GL_FUNC_ADD,
        "-": GL.GL_FUNC_SUBTRACT,
    }

    depth_func_map = {
        GL.GL_ALWAYS: "always",
        GL.GL_NEVER: "never",
        GL.GL_LESS: "<",
        GL.GL_EQUAL: "==",
        GL.GL_LEQUAL: "<=",
        GL.GL_GREATER: ">",
        GL.GL_NOTEQUAL: "!=",
        GL.GL_GEQUAL: ">=",
        "always": GL.GL_ALWAYS,
        "never": GL.GL_NEVER,
        "<": GL.GL_LESS,
        "==": GL.GL_EQUAL,
        "<=": GL.GL_LEQUAL,
        ">": GL.GL_GREATER,
        "!=": GL.GL_NOTEQUAL,
        ">=": GL.GL_GEQUAL,
    }

    stencil_func_map = {
        GL.GL_ALWAYS: "always",
        GL.GL_NEVER: "never",
        GL.GL_LESS: "<",
        GL.GL_EQUAL: "==",
        GL.GL_LEQUAL: "<=",
        GL.GL_GREATER: ">",
        GL.GL_NOTEQUAL: "!=",
        GL.GL_GEQUAL: ">=",
        "always": GL.GL_ALWAYS,
        "never": GL.GL_NEVER,
        "<": GL.GL_LESS,
        "==": GL.GL_EQUAL,
        "<=": GL.GL_LEQUAL,
        ">": GL.GL_GREATER,
        "!=": GL.GL_NOTEQUAL,
        ">=": GL.GL_GEQUAL,
    }

    internal_formats_map = {
        np.uint8: {1: GL.GL_R8, 2: GL.GL_RG8, 3: GL.GL_RGB8, 4: GL.GL_RGBA8},
        np.int8: {1: GL.GL_R8I, 2: GL.GL_RG8I, 3: GL.GL_RGB8I, 4: GL.GL_RGBA8I},
        np.uint16: {1: GL.GL_R16, 2: GL.GL_RG16, 3: GL.GL_RGB16, 4: GL.GL_RGBA16},
        np.int16: {1: GL.GL_R16I, 2: GL.GL_RG16I, 3: GL.GL_RGB16I, 4: GL.GL_RGBA16I},
        np.uint32: {
            1: GL.GL_R32UI,
            2: GL.GL_RG32UI,
            3: GL.GL_RGB32UI,
            4: GL.GL_RGBA32UI,
        },
        np.int32: {1: GL.GL_R32I, 2: GL.GL_RG32I, 3: GL.GL_RGB32I, 4: GL.GL_RGBA32I},
        np.float16: {1: GL.GL_R16F, 2: GL.GL_RG16F, 3: GL.GL_RGB16F, 4: GL.GL_RGBA16F},
        np.float32: {1: GL.GL_R32F, 2: GL.GL_RG32F, 3: GL.GL_RGB32F, 4: GL.GL_RGBA32F},
        # np.float64: {1: GL.GL_R64, 2: GL.GL_RG64F, 3: GL.GL_RGB64F, 4: GL.GL_RGBA64F}
        dtype_uint8: {1: GL.GL_R8, 2: GL.GL_RG8, 3: GL.GL_RGB8, 4: GL.GL_RGBA8},
        dtype_int8: {1: GL.GL_R8I, 2: GL.GL_RG8I, 3: GL.GL_RGB8I, 4: GL.GL_RGBA8I},
        dtype_uint16: {1: GL.GL_R16, 2: GL.GL_RG16, 3: GL.GL_RGB16, 4: GL.GL_RGBA16},
        dtype_int16: {1: GL.GL_R16I, 2: GL.GL_RG16I, 3: GL.GL_RGB16I, 4: GL.GL_RGBA16I},
        dtype_uint32: {
            1: GL.GL_R32UI,
            2: GL.GL_RG32UI,
            3: GL.GL_RGB32UI,
            4: GL.GL_RGBA32UI,
        },
        dtype_int32: {1: GL.GL_R32I, 2: GL.GL_RG32I, 3: GL.GL_RGB32I, 4: GL.GL_RGBA32I},
        dtype_float16: {
            1: GL.GL_R16F,
            2: GL.GL_RG16F,
            3: GL.GL_RGB16F,
            4: GL.GL_RGBA16F,
        },
        dtype_float32: {
            1: GL.GL_R32F,
            2: GL.GL_RG32F,
            3: GL.GL_RGB32F,
            4: GL.GL_RGBA32F,
        },
        # dtype_float64: {1: GL.GL_R64, 2: GL.GL_RG64F, 3: GL.GL_RGB64F, 4: GL.GL_RGBA64F}
    }

    format_info_map = {
        GL.GL_RED: [GL.GL_RED, GL.GL_UNSIGNED_BYTE],
        GL.GL_R8: [GL.GL_RED, GL.GL_UNSIGNED_BYTE],
        GL.GL_R8_SNORM: [GL.GL_RED, GL.GL_BYTE],
        GL.GL_R16: [GL.GL_RED, GL.GL_UNSIGNED_SHORT],
        GL.GL_R16_SNORM: [GL.GL_RED, GL.GL_SHORT],
        GL.GL_R16F: [GL.GL_RED, GL.GL_HALF_FLOAT],
        GL.GL_R32F: [GL.GL_RED, GL.GL_FLOAT],
        GL.GL_R8I: [GL.GL_RED_INTEGER, GL.GL_BYTE],
        GL.GL_R8UI: [GL.GL_RED_INTEGER, GL.GL_UNSIGNED_BYTE],
        GL.GL_R16I: [GL.GL_RED_INTEGER, GL.GL_SHORT],
        GL.GL_R16UI: [GL.GL_RED_INTEGER, GL.GL_UNSIGNED_SHORT],
        GL.GL_R32I: [GL.GL_RED_INTEGER, GL.GL_INT],
        GL.GL_R32UI: [GL.GL_RED_INTEGER, GL.GL_UNSIGNED_INT],
        GL.GL_COMPRESSED_RED: [GL.GL_RED, GL.GL_UNSIGNED_BYTE],
        GL.GL_COMPRESSED_RED_RGTC1: [GL.GL_RED, GL.GL_UNSIGNED_BYTE],
        GL.GL_COMPRESSED_SIGNED_RED_RGTC1: [GL.GL_RED, GL.GL_BYTE],
        GL.GL_RG: [GL.GL_RG, GL.GL_UNSIGNED_BYTE],
        GL.GL_RG8: [GL.GL_RG, GL.GL_UNSIGNED_BYTE],
        GL.GL_RG8_SNORM: [GL.GL_RG, GL.GL_BYTE],
        GL.GL_RG16: [GL.GL_RG, GL.GL_UNSIGNED_SHORT],
        GL.GL_RG16_SNORM: [GL.GL_RG, GL.GL_SHORT],
        GL.GL_RG16F: [GL.GL_RG, GL.GL_HALF_FLOAT],
        GL.GL_RG32F: [GL.GL_RG, GL.GL_FLOAT],
        GL.GL_RG8I: [GL.GL_RG_INTEGER, GL.GL_BYTE],
        GL.GL_RG8UI: [GL.GL_RG_INTEGER, GL.GL_UNSIGNED_BYTE],
        GL.GL_RG16I: [GL.GL_RG_INTEGER, GL.GL_SHORT],
        GL.GL_RG16UI: [GL.GL_RG_INTEGER, GL.GL_UNSIGNED_SHORT],
        GL.GL_RG32I: [GL.GL_RG_INTEGER, GL.GL_INT],
        GL.GL_RG32UI: [GL.GL_RG_INTEGER, GL.GL_UNSIGNED_INT],
        GL.GL_COMPRESSED_RG: [GL.GL_RG, GL.GL_UNSIGNED_BYTE],
        GL.GL_COMPRESSED_RG_RGTC2: [GL.GL_RG, GL.GL_UNSIGNED_BYTE],
        GL.GL_COMPRESSED_SIGNED_RG_RGTC2: [GL.GL_RG, GL.GL_BYTE],
        GL.GL_RGB: [GL.GL_RGB, GL.GL_UNSIGNED_BYTE],
        GL.GL_R3_G3_B2: [GL.GL_RGB, GL.GL_UNSIGNED_BYTE],
        GL.GL_RGB4: [GL.GL_RGB, GL.GL_UNSIGNED_BYTE],
        GL.GL_RGB5: [GL.GL_RGB, GL.GL_UNSIGNED_BYTE],
        GL.GL_RGB8: [GL.GL_RGB, GL.GL_UNSIGNED_BYTE],
        GL.GL_RGB8_SNORM: [GL.GL_RGB, GL.GL_BYTE],
        GL.GL_RGB10: [GL.GL_RGB, GL.GL_UNSIGNED_SHORT],
        GL.GL_RGB12: [GL.GL_RGB, GL.GL_UNSIGNED_SHORT],
        GL.GL_RGB16: [GL.GL_RGB, GL.GL_UNSIGNED_SHORT],
        GL.GL_RGB16_SNORM: [GL.GL_RGB, GL.GL_SHORT],
        GL.GL_SRGB8: [GL.GL_RGB, GL.GL_BYTE],
        GL.GL_RGB16F: [GL.GL_RGB, GL.GL_HALF_FLOAT],
        GL.GL_RGB32F: [GL.GL_RGB, GL.GL_FLOAT],
        GL.GL_R11F_G11F_B10F: [GL.GL_RGB, GL.GL_HALF_FLOAT],
        GL.GL_RGB9_E5: [GL.GL_RGB, GL.GL_SHORT],
        GL.GL_RGB8I: [GL.GL_RGB_INTEGER, GL.GL_BYTE],
        GL.GL_RGB8UI: [GL.GL_RGB_INTEGER, GL.GL_UNSIGNED_BYTE],
        GL.GL_RGB16I: [GL.GL_RGB_INTEGER, GL.GL_SHORT],
        GL.GL_RGB16UI: [GL.GL_RGB_INTEGER, GL.GL_UNSIGNED_SHORT],
        GL.GL_RGB32I: [GL.GL_RGB_INTEGER, GL.GL_INT],
        GL.GL_RGB32UI: [GL.GL_RGB_INTEGER, GL.GL_UNSIGNED_INT],
        GL.GL_COMPRESSED_RGB: [GL.GL_RGB, GL.GL_UNSIGNED_BYTE],
        GL.GL_COMPRESSED_SRGB: [GL.GL_RGB, GL.GL_UNSIGNED_BYTE],
        GL.GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT: [GL.GL_RGB, GL.GL_FLOAT],
        GL.GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT: [GL.GL_RGB, GL.GL_FLOAT],
        GL.GL_RGBA: [GL.GL_RGBA, GL.GL_UNSIGNED_BYTE],
        GL.GL_RGBA2: [GL.GL_RGBA, GL.GL_UNSIGNED_BYTE],
        GL.GL_RGBA4: [GL.GL_RGBA, GL.GL_UNSIGNED_BYTE],
        GL.GL_RGB5_A1: [GL.GL_RGBA, GL.GL_UNSIGNED_BYTE],
        GL.GL_RGBA8: [GL.GL_RGBA, GL.GL_UNSIGNED_BYTE],
        GL.GL_RGBA8_SNORM: [GL.GL_RGBA, GL.GL_BYTE],
        GL.GL_RGB10_A2: [GL.GL_RGBA, GL.GL_UNSIGNED_SHORT],
        GL.GL_RGB10_A2UI: [GL.GL_RGBA, GL.GL_UNSIGNED_SHORT],
        GL.GL_RGBA12: [GL.GL_RGBA, GL.GL_UNSIGNED_SHORT],
        GL.GL_RGBA16: [GL.GL_RGBA, GL.GL_UNSIGNED_SHORT],
        GL.GL_RGBA16_SNORM: [GL.GL_RGBA, GL.GL_UNSIGNED_SHORT],
        GL.GL_SRGB8_ALPHA8: [GL.GL_RGBA, GL.GL_UNSIGNED_BYTE],
        GL.GL_RGBA16F: [GL.GL_RGBA, GL.GL_HALF_FLOAT],
        GL.GL_RGBA32F: [GL.GL_RGBA, GL.GL_FLOAT],
        GL.GL_RGBA8I: [GL.GL_RGBA_INTEGER, GL.GL_BYTE],
        GL.GL_RGBA8UI: [GL.GL_RGBA_INTEGER, GL.GL_UNSIGNED_BYTE],
        GL.GL_RGBA16I: [GL.GL_RGBA_INTEGER, GL.GL_SHORT],
        GL.GL_RGBA16UI: [GL.GL_RGBA_INTEGER, GL.GL_UNSIGNED_SHORT],
        GL.GL_RGBA32I: [GL.GL_RGBA_INTEGER, GL.GL_INT],
        GL.GL_RGBA32UI: [GL.GL_RGBA_INTEGER, GL.GL_UNSIGNED_INT],
        GL.GL_COMPRESSED_RGBA: [GL.GL_RGBA, GL.GL_UNSIGNED_BYTE],
        GL.GL_COMPRESSED_SRGB_ALPHA: [GL.GL_RGBA, GL.GL_UNSIGNED_BYTE],
        GL.GL_COMPRESSED_RGBA_BPTC_UNORM: [GL.GL_RGBA, GL.GL_UNSIGNED_BYTE],
        GL.GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM: [GL.GL_RGBA, GL.GL_UNSIGNED_BYTE],
        GL.GL_DEPTH_COMPONENT: [GL.GL_DEPTH_COMPONENT, GL.GL_FLOAT],
        GL.GL_DEPTH_COMPONENT16: [GL.GL_DEPTH_COMPONENT, GL.GL_SHORT],
        GL.GL_DEPTH_COMPONENT24: [GL.GL_DEPTH_COMPONENT, GL.GL_INT],
        GL.GL_DEPTH_COMPONENT32: [GL.GL_DEPTH_COMPONENT, GL.GL_INT],
        GL.GL_DEPTH_COMPONENT32F: [GL.GL_DEPTH_COMPONENT, GL.GL_FLOAT],
        GL.GL_STENCIL_INDEX: [GL.GL_STENCIL_INDEX, GL.GL_UNSIGNED_BYTE],
        GL.GL_STENCIL_INDEX1: [GL.GL_STENCIL_INDEX, GL.GL_UNSIGNED_BYTE],
        GL.GL_STENCIL_INDEX4: [GL.GL_STENCIL_INDEX, GL.GL_UNSIGNED_BYTE],
        GL.GL_STENCIL_INDEX8: [GL.GL_STENCIL_INDEX, GL.GL_UNSIGNED_BYTE],
        GL.GL_STENCIL_INDEX16: [GL.GL_STENCIL_INDEX, GL.GL_UNSIGNED_SHORT],
        GL.GL_DEPTH_STENCIL: [GL.GL_DEPTH_STENCIL, GL.GL_FLOAT],
        GL.GL_DEPTH24_STENCIL8: [GL.GL_DEPTH_STENCIL, GL.GL_FLOAT],
        GL.GL_DEPTH32F_STENCIL8: [GL.GL_DEPTH_STENCIL, GL.GL_FLOAT],
    }

    enum_map = {
        value: value
        for name, value in vars(GL).items()
        if name.startswith("GL_") and isinstance(value, constant.IntConstant)
    }

    internal_formats = [
        GL.GL_RED,
        GL.GL_R8,
        GL.GL_R8_SNORM,
        GL.GL_R16,
        GL.GL_R16_SNORM,
        GL.GL_R16F,
        GL.GL_R32F,
        GL.GL_R8I,
        GL.GL_R8UI,
        GL.GL_R16I,
        GL.GL_R16UI,
        GL.GL_R32I,
        GL.GL_R32UI,
        GL.GL_COMPRESSED_RED,
        GL.GL_COMPRESSED_RED_RGTC1,
        GL.GL_COMPRESSED_SIGNED_RED_RGTC1,
        GL.GL_RG,
        GL.GL_RG8,
        GL.GL_RG8_SNORM,
        GL.GL_RG16,
        GL.GL_RG16_SNORM,
        GL.GL_RG16F,
        GL.GL_RG32F,
        GL.GL_RG8I,
        GL.GL_RG8UI,
        GL.GL_RG16I,
        GL.GL_RG16UI,
        GL.GL_RG32I,
        GL.GL_RG32UI,
        GL.GL_COMPRESSED_RG,
        GL.GL_COMPRESSED_RG_RGTC2,
        GL.GL_COMPRESSED_SIGNED_RG_RGTC2,
        GL.GL_RGB,
        GL.GL_R3_G3_B2,
        GL.GL_RGB4,
        GL.GL_RGB5,
        GL.GL_RGB8,
        GL.GL_RGB8_SNORM,
        GL.GL_RGB10,
        GL.GL_RGB12,
        GL.GL_RGB16,
        GL.GL_RGB16_SNORM,
        GL.GL_SRGB8,
        GL.GL_RGB16F,
        GL.GL_RGB32F,
        GL.GL_R11F_G11F_B10F,
        GL.GL_RGB9_E5,
        GL.GL_RGB8I,
        GL.GL_RGB8UI,
        GL.GL_RGB16I,
        GL.GL_RGB16UI,
        GL.GL_RGB32I,
        GL.GL_RGB32UI,
        GL.GL_COMPRESSED_RGB,
        GL.GL_COMPRESSED_SRGB,
        GL.GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT,
        GL.GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT,
        GL.GL_RGBA,
        GL.GL_RGBA2,
        GL.GL_RGBA4,
        GL.GL_RGB5_A1,
        GL.GL_RGBA8,
        GL.GL_RGBA8_SNORM,
        GL.GL_RGB10_A2,
        GL.GL_RGB10_A2UI,
        GL.GL_RGBA12,
        GL.GL_RGBA16,
        GL.GL_RGBA16_SNORM,
        GL.GL_SRGB8_ALPHA8,
        GL.GL_RGBA16F,
        GL.GL_RGBA32F,
        GL.GL_RGBA8I,
        GL.GL_RGBA8UI,
        GL.GL_RGBA16I,
        GL.GL_RGBA16UI,
        GL.GL_RGBA32I,
        GL.GL_RGBA32UI,
        GL.GL_COMPRESSED_RGBA,
        GL.GL_COMPRESSED_SRGB_ALPHA,
        GL.GL_COMPRESSED_RGBA_BPTC_UNORM,
        GL.GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM,
        GL.GL_DEPTH_COMPONENT,
        GL.GL_DEPTH_COMPONENT16,
        GL.GL_DEPTH_COMPONENT24,
        GL.GL_DEPTH_COMPONENT32,
        GL.GL_DEPTH_COMPONENT32F,
        GL.GL_STENCIL_INDEX,
        GL.GL_STENCIL_INDEX1,
        GL.GL_STENCIL_INDEX4,
        GL.GL_STENCIL_INDEX8,
        GL.GL_STENCIL_INDEX16,
        GL.GL_DEPTH_STENCIL,
        GL.GL_DEPTH24_STENCIL8,
        GL.GL_DEPTH32F_STENCIL8,
        None,
    ]

    color_internal_formats = [
        GL.GL_RED,
        GL.GL_R8,
        GL.GL_R8_SNORM,
        GL.GL_R16,
        GL.GL_R16_SNORM,
        GL.GL_R16F,
        GL.GL_R32F,
        GL.GL_R8I,
        GL.GL_R8UI,
        GL.GL_R16I,
        GL.GL_R16UI,
        GL.GL_R32I,
        GL.GL_R32UI,
        GL.GL_COMPRESSED_RED,
        GL.GL_COMPRESSED_RED_RGTC1,
        GL.GL_COMPRESSED_SIGNED_RED_RGTC1,
        GL.GL_RG,
        GL.GL_RG8,
        GL.GL_RG8_SNORM,
        GL.GL_RG16,
        GL.GL_RG16_SNORM,
        GL.GL_RG16F,
        GL.GL_RG32F,
        GL.GL_RG8I,
        GL.GL_RG8UI,
        GL.GL_RG16I,
        GL.GL_RG16UI,
        GL.GL_RG32I,
        GL.GL_RG32UI,
        GL.GL_COMPRESSED_RG,
        GL.GL_COMPRESSED_RG_RGTC2,
        GL.GL_COMPRESSED_SIGNED_RG_RGTC2,
        GL.GL_RGB,
        GL.GL_R3_G3_B2,
        GL.GL_RGB4,
        GL.GL_RGB5,
        GL.GL_RGB8,
        GL.GL_RGB8_SNORM,
        GL.GL_RGB10,
        GL.GL_RGB12,
        GL.GL_RGB16,
        GL.GL_RGB16_SNORM,
        GL.GL_SRGB8,
        GL.GL_RGB16F,
        GL.GL_RGB32F,
        GL.GL_R11F_G11F_B10F,
        GL.GL_RGB9_E5,
        GL.GL_RGB8I,
        GL.GL_RGB8UI,
        GL.GL_RGB16I,
        GL.GL_RGB16UI,
        GL.GL_RGB32I,
        GL.GL_RGB32UI,
        GL.GL_COMPRESSED_RGB,
        GL.GL_COMPRESSED_SRGB,
        GL.GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT,
        GL.GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT,
        GL.GL_RGBA,
        GL.GL_RGBA2,
        GL.GL_RGBA4,
        GL.GL_RGB5_A1,
        GL.GL_RGBA8,
        GL.GL_RGBA8_SNORM,
        GL.GL_RGB10_A2,
        GL.GL_RGB10_A2UI,
        GL.GL_RGBA12,
        GL.GL_RGBA16,
        GL.GL_RGBA16_SNORM,
        GL.GL_SRGB8_ALPHA8,
        GL.GL_RGBA16F,
        GL.GL_RGBA32F,
        GL.GL_RGBA8I,
        GL.GL_RGBA8UI,
        GL.GL_RGBA16I,
        GL.GL_RGBA16UI,
        GL.GL_RGBA32I,
        GL.GL_RGBA32UI,
        GL.GL_COMPRESSED_RGBA,
        GL.GL_COMPRESSED_SRGB_ALPHA,
        GL.GL_COMPRESSED_RGBA_BPTC_UNORM,
        GL.GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM,
    ]

    image_internal_formats = [
        GL.GL_RGBA32F,
        GL.GL_RGBA16F,
        GL.GL_RG32F,
        GL.GL_RG16F,
        GL.GL_R11F_G11F_B10F,
        GL.GL_R32F,
        GL.GL_R16F,
        GL.GL_RGBA16,
        GL.GL_RGB10_A2,
        GL.GL_RGBA8,
        GL.GL_RG16,
        GL.GL_RG8,
        GL.GL_R16,
        GL.GL_R8,
        GL.GL_RGBA16_SNORM,
        GL.GL_RGBA8_SNORM,
        GL.GL_RG16_SNORM,
        GL.GL_RG8_SNORM,
        GL.GL_R16_SNORM,
        None,
    ]

    isampler_internal_formats = [
        GL.GL_RGBA32I,
        GL.GL_RGBA16I,
        GL.GL_RGBA8I,
        GL.GL_RGB32I,
        GL.GL_RGB16I,
        GL.GL_RGB8I,
        GL.GL_RG32I,
        GL.GL_RG16I,
        GL.GL_RG8I,
        GL.GL_R32I,
        GL.GL_R16I,
        GL.GL_R8I,
        None,
    ]

    iimage_internal_formats = [
        GL.GL_RGBA32I,
        GL.GL_RGBA16I,
        GL.GL_RGBA8I,
        GL.GL_RG32I,
        GL.GL_RG16I,
        GL.GL_RG8I,
        GL.GL_R32I,
        GL.GL_R16I,
        GL.GL_R8I,
        None,
    ]

    usampler_internal_formats = [
        GL.GL_RGBA32UI,
        GL.GL_RGBA16UI,
        GL.GL_RGB10_A2UI,
        GL.GL_RGBA8UI,
        GL.GL_RGB32UI,
        GL.GL_RGB16UI,
        GL.GL_RGB8UI,
        GL.GL_RG32UI,
        GL.GL_RG16UI,
        GL.GL_RG8UI,
        GL.GL_R32UI,
        GL.GL_R16UI,
        GL.GL_R8UI,
        None,
    ]

    uimage_internal_formats = [
        GL.GL_RGBA32UI,
        GL.GL_RGBA16UI,
        GL.GL_RGB10_A2UI,
        GL.GL_RGBA8UI,
        GL.GL_RG32UI,
        GL.GL_RG16UI,
        GL.GL_RG8UI,
        GL.GL_R32UI,
        GL.GL_R16UI,
        GL.GL_R8UI,
        None,
    ]

    depth_internal_formats = [
        GL.GL_DEPTH_COMPONENT,
        GL.GL_DEPTH_COMPONENT16,
        GL.GL_DEPTH_COMPONENT24,
        GL.GL_DEPTH_COMPONENT32,
        GL.GL_DEPTH_COMPONENT32F,
    ]

    stencil_internal_formats = [
        GL.GL_STENCIL_INDEX,
        GL.GL_STENCIL_INDEX1,
        GL.GL_STENCIL_INDEX4,
        GL.GL_STENCIL_INDEX8,
        GL.GL_STENCIL_INDEX16,
    ]

    depth_stencil_internal_formats = [
        GL.GL_DEPTH_STENCIL,
        GL.GL_DEPTH24_STENCIL8,
        GL.GL_DEPTH32F_STENCIL8,
    ]

    fog_modes = [GL.GL_LINEAR, GL.GL_EXP, GL.GL_EXP2]

    dtypes = [
        GL.GL_BYTE,
        GL.GL_UNSIGNED_BYTE,
        GL.GL_SHORT,
        GL.GL_UNSIGNED_SHORT,
        GL.GL_INT,
        GL.GL_UNSIGNED_INT,
        GL.GL_HALF_FLOAT,
        GL.GL_FLOAT,
        GL.GL_DOUBLE,
        None,
    ]

    operations = [
        GL.GL_KEEP,  # 保持模板缓冲区的当前值
        GL.GL_ZERO,  # 将模板缓冲区的值设置为 0
        GL.GL_REPLACE,  # 将模板缓冲区的值替换为参考值（通过 glStencilFunc() 设置）
        GL.GL_INCR,  # 将模板缓冲区的值递增 1（如果结果超出了模板缓冲区的范围，将会回环到 0）
        GL.GL_DECR,  # 将模板缓冲区的值递减 1（如果结果小于 0，将会回环到最大值）
        GL.GL_INVERT,  # 按位取反模板缓冲区的值
    ]

    shader_ext_map = {
        ".vert": GL.GL_VERTEX_SHADER,
        ".tesc": GL.GL_TESS_CONTROL_SHADER,
        ".tese": GL.GL_TESS_EVALUATION_SHADER,
        ".geom": GL.GL_GEOMETRY_SHADER,
        ".frag": GL.GL_FRAGMENT_SHADER,
        ".comp": GL.GL_COMPUTE_SHADER,
        ".vs": GL.GL_VERTEX_SHADER,
        ".tcs": GL.GL_TESS_CONTROL_SHADER,
        ".tes": GL.GL_TESS_EVALUATION_SHADER,
        ".gs": GL.GL_GEOMETRY_SHADER,
        ".fs": GL.GL_FRAGMENT_SHADER,
        ".cs": GL.GL_COMPUTE_SHADER,
        GL.GL_VERTEX_SHADER: ".vert",
        GL.GL_TESS_CONTROL_SHADER: ".tesc",
        GL.GL_TESS_EVALUATION_SHADER: ".tese",
        GL.GL_GEOMETRY_SHADER: ".geom",
        GL.GL_FRAGMENT_SHADER: ".frag",
        GL.GL_COMPUTE_SHADER: ".comp",
    }

    primitive_type_map = {
        "points": [GL.GL_POINTS],
        "lines": [GL.GL_LINES, GL.GL_LINE_STRIP, GL.GL_LINE_LOOP],
        "lines_adjacency": [GL.GL_LINES_ADJACENCY, GL.GL_LINE_STRIP_ADJACENCY],
        "triangles": [GL.GL_TRIANGLES, GL.GL_TRIANGLE_STRIP, GL.GL_TRIANGLE_FAN],
        "triangles_adjacency": [
            GL.GL_TRIANGLES_ADJACENCY,
            GL.GL_TRIANGLE_STRIP_ADJACENCY,
        ],
    }

    polygon_modes = [GL.GL_FILL, GL.GL_LINE, GL.GL_POINT]

    depth_funcs = [
        GL.GL_ALWAYS,
        GL.GL_NEVER,
        GL.GL_LESS,
        GL.GL_EQUAL,
        GL.GL_LEQUAL,
        GL.GL_GREATER,
        GL.GL_NOTEQUAL,
        GL.GL_GEQUAL,
    ]

    depth_func_strs = ["always", "never", "<", "==", "<=", ">", "!=", ">="]

    stencil_funcs = [
        GL.GL_ALWAYS,
        GL.GL_NEVER,
        GL.GL_LESS,
        GL.GL_EQUAL,
        GL.GL_LEQUAL,
        GL.GL_GREATER,
        GL.GL_NOTEQUAL,
        GL.GL_GEQUAL,
    ]

    stencil_func_strs = ["always", "never", "<", "==", "<=", ">", "!=", ">="]

    shader_types = [
        GL.GL_VERTEX_SHADER,
        GL.GL_FRAGMENT_SHADER,
        GL.GL_GEOMETRY_SHADER,
        GL.GL_TESS_CONTROL_SHADER,
        GL.GL_TESS_EVALUATION_SHADER,
        None,
    ]

    wrap_types = [
        GL.GL_REPEAT,
        GL.GL_MIRRORED_REPEAT,
        GL.GL_CLAMP_TO_EDGE,
        GL.GL_CLAMP_TO_BORDER,
        GL.GL_MIRROR_CLAMP_TO_EDGE,
    ]

    filter_types = [GL.GL_NEAREST, GL.GL_LINEAR, None]

    none_color_attachment_types = [
        GL.GL_DEPTH_ATTACHMENT,
        GL.GL_STENCIL_ATTACHMENT,
        GL.GL_DEPTH_STENCIL_ATTACHMENT,
    ]

    draw_types = [
        GL.GL_STATIC_DRAW,
        GL.GL_DYNAMIC_DRAW,
        GL.GL_STREAM_DRAW,
        GL.GL_DYNAMIC_COPY,
    ]

    triangle_types = [GL.GL_TRIANGLES, GL.GL_TRIANGLE_STRIP, GL.GL_TRIANGLE_FAN]

    line_types = [GL.GL_LINES, GL.GL_LINE_LOOP, GL.GL_LINE_STRIP]

    primitive_types = [*triangle_types, *line_types, GL.GL_POINTS, GL.GL_PATCHES]

    cull_face_types = [GL.GL_BACK, GL.GL_FRONT, GL.GL_FRONT_AND_BACK, None]

    blend_equations = [GL.GL_FUNC_ADD, GL.GL_FUNC_SUBTRACT, GL.GL_FUNC_REVERSE_SUBTRACT]

    blend_funcs = [
        GL.GL_ZERO,
        GL.GL_ONE,
        GL.GL_SRC_COLOR,
        GL.GL_ONE_MINUS_SRC_COLOR,
        GL.GL_DST_COLOR,
        GL.GL_ONE_MINUS_DST_COLOR,
        GL.GL_SRC_ALPHA,
        GL.GL_ONE_MINUS_SRC_ALPHA,
        GL.GL_DST_ALPHA,
        GL.GL_ONE_MINUS_DST_ALPHA,
        GL.GL_CONSTANT_COLOR,
        GL.GL_ONE_MINUS_CONSTANT_COLOR,
        GL.GL_CONSTANT_ALPHA,
        GL.GL_ONE_MINUS_CONSTANT_ALPHA,
    ]

    attr_types = (
        int,
        float,
        glm.vec2,
        glm.ivec2,
        glm.uvec2,
        glm.dvec2,
        glm.vec3,
        glm.ivec3,
        glm.uvec3,
        glm.dvec3,
        glm.vec4,
        glm.ivec4,
        glm.uvec4,
        glm.dvec4,
        glm.mat2x2,
        glm.mat2x3,
        glm.mat2x4,
        glm.mat3x2,
        glm.mat3x3,
        glm.mat3x4,
        glm.mat4x2,
        glm.mat4x3,
        glm.mat4x4,
        glm.dmat2x2,
        glm.dmat2x3,
        glm.dmat2x4,
        glm.dmat3x2,
        glm.dmat3x3,
        glm.dmat3x4,
        glm.dmat4x2,
        glm.dmat4x3,
        glm.dmat4x4,
    )

    int_types = [
        GL.GL_BYTE,
        GL.GL_UNSIGNED_BYTE,
        GL.GL_SHORT,
        GL.GL_UNSIGNED_SHORT,
        GL.GL_INT,
        GL.GL_UNSIGNED_INT,
    ]

    atom_type_names = [
        "bool",
        "int",
        "uint",
        "uint64_t",
        "float",
        "double",
        "atomic_uint",
        "bvec2",
        "bvec3",
        "bvec4",
        "ivec2",
        "ivec3",
        "ivec4",
        "uvec2",
        "uvec3",
        "uvec4",
        "vec2",
        "vec3",
        "vec4",
        "dvec2",
        "dvec3",
        "dvec4",
        "mat2x2",
        "mat3x2",
        "mat4x2",
        "mat2x3",
        "mat3x3",
        "mat4x3",
        "mat2x4",
        "mat3x4",
        "mat4x4",
        "mat2",
        "mat3",
        "mat4",
        "dmat2x2",
        "dmat3x2",
        "dmat4x2",
        "dmat2x3",
        "dmat3x3",
        "dmat4x3",
        "dmat2x4",
        "dmat3x4",
        "dmat4x4",
        "dmat2",
        "dmat3",
        "dmat4",
        "sampler1D",
        "isampler1D",
        "usampler1D",
        "sampler2D",
        "isampler2D",
        "usampler2D",
        "sampler3D",
        "isampler3D",
        "usampler3D",
        "sampler1DShadow",
        "isampler1DShadow",
        "usampler1DShadow",
        "sampler2DShadow",
        "isampler2DShadow",
        "usampler2DShadow",
        "sampler3DShadow",
        "isampler3DShadow",
        "usampler3DShadow",
        "sampler1DArray",
        "isampler1DArray",
        "usampler1DArray",
        "sampler2DArray",
        "isampler2DArray",
        "usampler2DArray",
        "sampler1DArrayShadow",
        "isampler1DArrayShadow",
        "usampler1DArrayShadow",
        "sampler2DArrayShadow",
        "isampler2DArrayShadow",
        "usampler2DArrayShadow",
        "sampler2DMS",
        "isampler2DMS",
        "usampler2DMS",
        "sampler2DMSArray",
        "isampler2DMSArray",
        "usampler2DMSArray",
        "samplerCube",
        "isamplerCube",
        "usamplerCube",
        "samplerCubeArray",
        "isamplerCubeArray",
        "usamplerCubeArray",
        "samplerCubeShadow",
        "isamplerCubeShadow",
        "usamplerCubeShadow",
        "samplerCubeArrayShadow",
        "isamplerCubeArrayShadow",
        "usamplerCubeArrayShadow",
        "sampler2DRect",
        "isampler2DRect",
        "usampler2DRect",
        "sampler2DRectShadow",
        "isampler2DRectShadow",
        "usampler2DRectShadow",
        "samplerBuffer",
        "isamplerBuffer",
        "usamplerBuffer",
        "image1D",
        "iimage1D",
        "uimage1D",
        "image2D",
        "iimage2D",
        "uimage2D",
        "image3D",
        "iimage3D",
        "uimage3D",
        "imageCube",
        "iimageCube",
        "uimageCube",
        "imageCubeArray",
        "iimageCubeArray",
        "uimageCubeArray",
        "image2DRect",
        "iimage2DRect",
        "iimage2DRect",
        "image2DRect",
        "iimage2DRect",
        "iimage2DRect",
        "image1DArray",
        "iimage1DArray",
        "iimage1DArray",
        "image2DArray",
        "iimage2DArray",
        "uimage2DArray",
        "imageBuffer",
        "iimageBuffer",
        "uimageBuffer",
        "image2DMS",
        "iimage2DMS",
        "uimage2DMS",
        "image2DMSArray",
        "iimage2DMSArray",
        "uimage2DMSArray",
    ]

    basic_types = ["bool", "int", "uint", "float", "double"]
    gvec2_types = ["bvec2", "ivec2", "uvec2", "vec2", "dvec2"]
    gvec3_types = ["bvec3", "ivec3", "uvec3", "vec3", "dvec3"]
    gvec4_types = ["bvec4", "ivec4", "uvec4", "vec4", "dvec4"]
    gmat2x2_types = [("mat2x2", "mat2"), ("dmat2x2", "dmat2")]
    gmat3x2_types = ["mat3x2", "dmat3x2"]
    gmat3x3_types = [("mat3x3", "mat3"), ("dmat3x3", "dmat3")]
    gmat3x4_types = ["mat3x4", "dmat3x4"]
    gmat4x2_types = ["mat4x2", "dmat4x2"]
    gmat4x3_types = ["mat4x3", "dmat4x3"]
    gmat4x4_types = [("mat4x4", "mat4"), ("dmat4x4", "dmat4")]

    atom_type_map = {
        "bool": (bool, "bool", ""),
        "int": (int, "int", ""),
        "uint": (np.uint32, "uint", ""),
        "uint64_t": (np.uint64, "uint", ""),
        "float": (np.float32, "float", ""),
        "double": (np.float64, "double", ""),
        "atomic_uint": (np.uint32, "uint", ""),
        "bvec2": (glm.bvec2, "bool", "vec2"),
        "bvec3": (glm.bvec3, "bool", "vec3"),
        "bvec4": (glm.bvec4, "bool", "vec4"),
        "ivec2": (glm.ivec2, "int", "vec2"),
        "ivec3": (glm.ivec3, "int", "vec3"),
        "ivec4": (glm.ivec4, "int", "vec4"),
        "uvec2": (glm.uvec2, "uint", "vec2"),
        "uvec3": (glm.uvec3, "uint", "vec3"),
        "uvec4": (glm.uvec4, "uint", "vec4"),
        "vec2": (glm.vec2, "float", "vec2"),
        "vec3": (glm.vec3, "float", "vec3"),
        "vec4": (glm.vec4, "float", "vec4"),
        "dvec2": (glm.dvec2, "double", "vec2"),
        "dvec3": (glm.dvec3, "double", "vec3"),
        "dvec4": (glm.dvec4, "double", "vec4"),
        "mat2x2": (glm.mat2x2, "float", "mat2x2"),
        "mat3x2": (glm.mat3x2, "float", "mat3x2"),
        "mat4x2": (glm.mat4x2, "float", "mat4x2"),
        "mat2x3": (glm.mat2x3, "float", "mat2x3"),
        "mat3x3": (glm.mat3x3, "float", "mat3x3"),
        "mat4x3": (glm.mat4x3, "float", "mat4x3"),
        "mat2x4": (glm.mat2x4, "float", "mat2x4"),
        "mat3x4": (glm.mat3x4, "float", "mat3x4"),
        "mat4x4": (glm.mat4x4, "float", "mat4x4"),
        "mat2": (glm.mat2, "float", "mat2x2"),
        "mat3": (glm.mat3, "float", "mat3x3"),
        "mat4": (glm.mat4, "float", "mat4x4"),
        "dmat2x2": (glm.dmat2x2, "double", "mat2x2"),
        "dmat3x2": (glm.dmat3x2, "double", "mat3x2"),
        "dmat4x2": (glm.dmat4x2, "double", "mat4x2"),
        "dmat2x3": (glm.dmat2x3, "double", "mat2x3"),
        "dmat3x3": (glm.dmat3x3, "double", "mat3x3"),
        "dmat4x3": (glm.dmat4x3, "double", "mat4x3"),
        "dmat2x4": (glm.dmat2x4, "double", "mat2x4"),
        "dmat3x4": (glm.dmat3x4, "double", "mat3x4"),
        "dmat4x4": (glm.dmat4x4, "double", "mat4x4"),
        "dmat2": (glm.dmat2, "double", "mat2x2"),
        "dmat3": (glm.dmat3, "double", "mat3x3"),
        "dmat4": (glm.dmat4, "double", "mat4x4"),
    }

    memory_modifiers_to_internal_types_map = {
        "r11f_g11f_b10f": GL.GL_R11F_G11F_B10F,
        "rgba16_snorm": GL.GL_RGBA16_SNORM,
        "rgba8_snorm": GL.GL_RGBA8_SNORM,
        "rg16_snorm": GL.GL_RG16_SNORM,
        "rgb10_a2ui": GL.GL_RGB10_A2UI,
        "rg8_snorm": GL.GL_RG8_SNORM,
        "r16_snorm": GL.GL_R16_SNORM,
        "r8_snorm": GL.GL_R8_SNORM,
        "rgb10_a2": GL.GL_RGB10_A2,
        "rgba32ui": GL.GL_RGBA32UI,
        "rgba16ui": GL.GL_RGBA16UI,
        "rgba8ui": GL.GL_RGBA8UI,
        "rgba32f": GL.GL_RGBA32F,
        "rgba16f": GL.GL_RGBA16F,
        "rgba32i": GL.GL_RGBA32UI,
        "rgba16i": GL.GL_RGBA16I,
        "rgba16": GL.GL_RGBA16,
        "rgba8i": GL.GL_RGBA8I,
        "rg32ui": GL.GL_RG32UI,
        "rg16ui": GL.GL_RG16UI,
        "rg8ui": GL.GL_RG8UI,
        "r32ui": GL.GL_R32UI,
        "r16ui": GL.GL_R16UI,
        "rg32i": GL.GL_RG32I,
        "rg16i": GL.GL_RG16I,
        "rg32f": GL.GL_RG32F,
        "rg16f": GL.GL_RG16F,
        "rgba8": GL.GL_RGBA8,
        "rg8i": GL.GL_RG8I,
        "r32i": GL.GL_R32I,
        "r16i": GL.GL_R16I,
        "r32f": GL.GL_R32F,
        "r16f": GL.GL_R16F,
        "rg16": GL.GL_RG16,
        "r8ui": GL.GL_R8UI,
        "r8i": GL.GL_R8I,
        "rg8": GL.GL_RG8,
        "r16": GL.GL_R16,
        "r8": GL.GL_R8,
    }
    mipmap_filter_map = {
        (GL.GL_NEAREST, GL.GL_NEAREST): GL.GL_NEAREST_MIPMAP_NEAREST,
        (GL.GL_NEAREST, GL.GL_LINEAR): GL.GL_NEAREST_MIPMAP_LINEAR,
        (GL.GL_LINEAR, GL.GL_NEAREST): GL.GL_LINEAR_MIPMAP_NEAREST,
        (GL.GL_LINEAR, GL.GL_LINEAR): GL.GL_LINEAR_MIPMAP_LINEAR,
    }
    fbo_status_errors = {
        GL.GL_FRAMEBUFFER_UNDEFINED: "default FBO does not exist",
        GL.GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: "some attachments are incomplete",
        GL.GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: "no attachments attached",
        GL.GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER: "all color attachments' GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE is GL_NONE",
        GL.GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER: "all read buffer color attachments' GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE is GL_NONE",
        GL.GL_FRAMEBUFFER_UNSUPPORTED: "the combination of attachments' internal formats violates an implementation-dependent set of restrictions",
        GL.GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE: [
            "GL_RENDERBUFFER_SAMPLES is not the same for all attached RBOs",
            "GL_TEXTURE_SAMPLES is the not same for all attached textures",
            "attachments are a mix of RBOs and textures, but GL_RENDERBUFFER_SAMPLES doesn't match GL_TEXTURE_SAMPLES",
            "GL_TEXTURE_FIXED_SAMPLE_LOCATIONS is not the same for all attached textures",
            "attachments are a mix of RBOs and textures, but GL_TEXTURE_FIXED_SAMPLE_LOCATIONS is not GL_TRUE for all attached textures",
        ],
        GL.GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS: [
            "some attachments are layered, but some populated attachments are not layered",
            "all populated color attachments are not from textures of the same target",
        ],
    }
